/*
 * Copyright (c) 2009. Silenus Consultoria, S.L.
 */
package es.silenus.detecta.controller;

import es.silenus.detecta.Constants;

import es.silenus.detecta.dao.KnowledgeAreaDAO;
import es.silenus.detecta.dao.KnowledgePathDAO;
import es.silenus.detecta.dao.KnowledgeUnitDAO;
import es.silenus.detecta.dao.Page;

import es.silenus.detecta.model.*;

import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * Knowledge area controller.
 *
 * @author <a href="mailto:malonso@silenus-consultoria.es">Mariano Alonso</a>
 *
 * @since 06-abr-2009 20:28:09
 */
public class KnowledgeAreaController extends BaseController {
	/**
	 * Sets the knowledge area DAO.
	 */
	private KnowledgeAreaDAO knowledgeAreaDAO;

	/**
	 * The knowledge path DAO.
	 */
	private KnowledgePathDAO knowledgePathDAO;

	/**
	 * The knowledge unit DAO.
	 */
	private KnowledgeUnitDAO knowledgeUnitDAO;

	/**
	 * Sets the knowledge area DAO.
	 *
	 * @param knowledgeAreaDAO the knowledge area DAO.
	 */
	public void setKnowledgeAreaDAO(final KnowledgeAreaDAO knowledgeAreaDAO) {
		this.knowledgeAreaDAO = knowledgeAreaDAO;
	}

	/**
	 * Sets the knowledge path DAO.
	 *
	 * @param knowledgePathDAO the knowledge path DAO.
	 */
	public void setKnowledgePathDAO(final KnowledgePathDAO knowledgePathDAO) {
		this.knowledgePathDAO = knowledgePathDAO;
	}

	/**
	 * Sets the knowledge unit DAO.
	 *
	 * @param knowledgeUnitDAO the knowledgeUnit DAO.
	 */
	public void setKnowledgeUnitDAO(final KnowledgeUnitDAO knowledgeUnitDAO) {
		this.knowledgeUnitDAO = knowledgeUnitDAO;
	}

	/**
	 * Retrieves areas.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String getAreas(final HttpServletRequest request, final HttpServletResponse response) {
		User current = getUser(request);

		String query = request.getParameter("query");

		List<KnowledgeArea> areas;

		if((query != null) && (query.length() > 0)) {
			Map<String, Object> sample = new HashMap<String, Object>();

			sample.put("description", query);
			//sample.put("code", query);
			sample.put("organization.id", current.getOrganization().getId());

			areas = knowledgeAreaDAO.findByExample(sample);
		} else {
			areas = knowledgeAreaDAO.findByOrganization(current.getOrganization().getId());
		}

		request.setAttribute("areas", areas);

		return "secure/organization/areas";
	}

	/**
	 * Finds areas.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String findAreas(final HttpServletRequest request, final HttpServletResponse response) {
		User current = getUser(request);

		Map<String, Object> sample = new HashMap<String, Object>();
		String temp = request.getParameter("id");

		if(temp != null) {
			sample.put("id", temp);
		}

		temp = request.getParameter("code");

		if(temp != null) {
			sample.put("code", temp);
		}

		temp = request.getParameter("description");

		if(temp != null) {
			temp = StringUtils.replaceChars(temp, CharUtils.CR, ' ');
			temp = StringUtils.replaceChars(temp, CharUtils.LF, ' ');
			sample.put("description", temp);
		}

		sample.put("organization.id", current.getOrganization().getId());

		int start = Integer.parseInt(request.getParameter("start"));
		int limit = Integer.parseInt(request.getParameter("limit"));
		String[] sortFields = request.getParameterValues("sort");
		String[] sortDirections = request.getParameterValues("dir");

		Page<KnowledgeArea> page = knowledgeAreaDAO.findByExample(sample, start, limit, sortFields, sortDirections);

		request.setAttribute("page", page);


		return "secure/organization/area-search";
	}

	/**
	 * Updates an area.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String updateArea(final HttpServletRequest request, final HttpServletResponse response) {
		User current = getUser(request);
		Organization organization = current.getOrganization();

		String id = request.getParameter("id");

		int areaId = (id != null) ? Integer.parseInt(id) : 0;

		KnowledgeArea area;

		if(areaId > 0) {
			area = knowledgeAreaDAO.findById(areaId);
		} else {
			area = new KnowledgeArea();
		}

		String temp = request.getParameter("code");

		if(temp != null) {
			area.setCode(temp);

			KnowledgeArea otherArea = knowledgeAreaDAO.findByCode(temp, organization.getId());

			if((otherArea != null) && (otherArea.getId() != areaId)) {
				request.setAttribute(Constants.ERRORS, "area.code.duplicated");

				return "secure/organization/area-update-error";
			}
		}

		temp = request.getParameter("description");
		temp = StringUtils.replaceChars(temp, CharUtils.CR, ' ');
		temp = StringUtils.replaceChars(temp, CharUtils.LF, ' ');
		area.setDescription(temp);
		area.setOrganization(organization);

		if(areaId > 0) {
			knowledgeAreaDAO.update(area);
		} else {
			knowledgeAreaDAO.save(area);
		}

		request.setAttribute("area", area);

		return "secure/organization/area-updated";
	}

	/**
	 * Finds paths.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String findPaths(final HttpServletRequest request, final HttpServletResponse response) {
		User current = getUser(request);

		Map<String, Object> sample = new HashMap<String, Object>();
		String temp = request.getParameter("id");

		if(temp != null) {
			sample.put("id", temp);
		}

		temp = request.getParameter("code");

		if(temp != null) {
			sample.put("code", temp);
		}

		temp = request.getParameter("description");

		if(temp != null) {
			temp = StringUtils.replaceChars(temp, CharUtils.CR, ' ');
			temp = StringUtils.replaceChars(temp, CharUtils.LF, ' ');
			sample.put("description", temp);
		}

		temp = request.getParameter("area");

		if(temp != null) {
			sample.put("area.id", Integer.parseInt(temp));
		}

		sample.put("organization.id", current.getOrganization().getId());

		int start = Integer.parseInt(request.getParameter("start"));
		int limit = Integer.parseInt(request.getParameter("limit"));
		String[] sortFields = request.getParameterValues("sort");
		String[] sortDirections = request.getParameterValues("dir");

		Page<KnowledgePath> page = knowledgePathDAO.findByExample(sample, start, limit, sortFields, sortDirections);

		request.setAttribute("page", page);


		return "secure/organization/path-search";
	}

	/**
	 * Updates a path.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String updatePath(final HttpServletRequest request, final HttpServletResponse response) {
		User current = getUser(request);

		String id = request.getParameter("id");

		int pathId = (id != null) ? Integer.parseInt(id) : 0;

		KnowledgePath path;

		if(pathId > 0) {
			path = knowledgePathDAO.findById(pathId);
		} else {
			path = new KnowledgePath();
		}

		KnowledgeArea area = knowledgeAreaDAO.findById(Integer.parseInt(request.getParameter("area")));

		String temp = request.getParameter("code");

		if(temp != null) {
			path.setCode(temp);

			KnowledgePath otherPath = knowledgePathDAO.findByCode(temp, area.getId());

			if((otherPath != null) && (otherPath.getId() != pathId)) {
				request.setAttribute(Constants.ERRORS, "path.code.duplicated");

				return "secure/organization/path-update-error";
			}
		}

		temp = request.getParameter("description");
		temp = StringUtils.replaceChars(temp, CharUtils.CR, ' ');
		temp = StringUtils.replaceChars(temp, CharUtils.LF, ' ');
		path.setDescription(temp);
		path.setArea(area);

		if(pathId > 0) {
			knowledgePathDAO.update(path);
		} else {
			knowledgePathDAO.save(path);
		}

		request.setAttribute("path", path);

		return "secure/organization/path-updated";
	}

	/**
	 * Retrieves the paths.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String getPaths(final HttpServletRequest request, final HttpServletResponse response) {
		User current = getUser(request);

		String query = request.getParameter("query");

		List<KnowledgePath> result;

		if((query != null) && (query.length() > 0)) {
			Map<String, Object> sample = new HashMap<String, Object>();

			sample.put("description", query);
			//sample.put("code", query);
			sample.put("organization.id", current.getOrganization().getId());

			result = knowledgePathDAO.findByExample(sample);
		} else {
			result = knowledgePathDAO.findByOrganization(current.getOrganization().getId());
		}


		request.setAttribute("result", result);

		return "secure/organization/paths";
	}

	/**
	 * Find associated units.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String findAssociatedUnits(final HttpServletRequest request, final HttpServletResponse response) {
		int id = Integer.parseInt(request.getParameter("id"));

		Map<String, Object> sample = new HashMap<String, Object>();

		sample.put("id", id);

		int start = Integer.parseInt(request.getParameter("start"));
		int limit = Integer.parseInt(request.getParameter("limit"));
		String[] sortFields = request.getParameterValues("sort");
		String[] sortDirections = request.getParameterValues("dir");


		Page<KnowledgeUnit> page = knowledgePathDAO.findAssociatedUnits(sample, start, limit, sortFields, sortDirections);

		request.setAttribute("page", page);

		return "secure/organization/units";
	}

	/**
	 * Find non-associated units.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String findNonAssociatedUnits(final HttpServletRequest request, final HttpServletResponse response) {
		int id = Integer.parseInt(request.getParameter("id"));

		Map<String, Object> sample = new HashMap<String, Object>();

		sample.put("id", id);

		int start = Integer.parseInt(request.getParameter("start"));
		int limit = Integer.parseInt(request.getParameter("limit"));
		String[] sortFields = request.getParameterValues("sort");
		String[] sortDirections = request.getParameterValues("dir");


		Page<KnowledgeUnit> page = knowledgePathDAO.findNonAssociatedUnits(
				sample, start, limit, sortFields, sortDirections);

		request.setAttribute("page", page);

		return "secure/organization/units";
	}

	/**
	 * Adds a unit.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String addUnit(final HttpServletRequest request, final HttpServletResponse response) {
		int id = Integer.parseInt(request.getParameter("id"));
		String[] units = request.getParameterValues("units");

		if(units != null) {
			Long[] unitIds = new Long[units.length];

			for(int i = 0; i < units.length; ++i) {
				unitIds[i] = Long.parseLong(units[i]);
			}

			KnowledgePath knowledgePath = knowledgePathDAO.findById(id);
			List<KnowledgeUnit> theUnits = knowledgeUnitDAO.findByIds(unitIds);

			knowledgePath.getUnits().addAll(theUnits);
			knowledgePathDAO.update(knowledgePath);
		}

		return "secure/organization/unit-added";
	}

	/**
	 * Removes a unit.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String removeUnit(final HttpServletRequest request, final HttpServletResponse response) {
		int id = Integer.parseInt(request.getParameter("id"));
		String[] units = request.getParameterValues("units");

		if(units != null) {
			Long[] unitIds = new Long[units.length];

			for(int i = 0; i < units.length; ++i) {
				unitIds[i] = Long.parseLong(units[i]);
			}

			KnowledgePath knowledgePath = knowledgePathDAO.findById(id);
			List<KnowledgeUnit> theUnits = knowledgeUnitDAO.findByIds(unitIds);

			knowledgePath.getUnits().removeAll(theUnits);
			knowledgePathDAO.update(knowledgePath);
		}

		return "secure/organization/unit-removed";
	}

	/**
	 * Checks remove areas.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String checkDeleteAreas(final HttpServletRequest request, final HttpServletResponse response) {
		String[] areas = request.getParameterValues("elements");

		if(areas != null) {
			Integer[] areaIds = new Integer[areas.length];

			for(int i = 0; i < areas.length; ++i) {
				areaIds[i] = Integer.parseInt(areas[i]);
			}

			List theAreas = knowledgeAreaDAO.getRemovalInformation(areaIds);

			request.setAttribute("areas", theAreas);
		}

		return "secure/organization/areas-check-removed";
	}

	/**
	 * Remove areas.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String deleteAreas(final HttpServletRequest request, final HttpServletResponse response) {
		String[] areas = request.getParameterValues("elements");

		if(areas != null) {
			Integer[] areaIds = new Integer[areas.length];

			for(int i = 0; i < areas.length; ++i) {
				areaIds[i] = Integer.parseInt(areas[i]);
			}

			knowledgeAreaDAO.remove(areaIds);
		}

		return "secure/organization/areas-removed";
	}

	/**
	 * Checks remove paths.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String checkDeletePaths(final HttpServletRequest request, final HttpServletResponse response) {
		String[] paths = request.getParameterValues("elements");

		if(paths != null) {
			Integer[] pathIds = new Integer[paths.length];

			for(int i = 0; i < paths.length; ++i) {
				pathIds[i] = Integer.parseInt(paths[i]);
			}

			List thePaths = knowledgePathDAO.getRemovalInformation(pathIds);

			request.setAttribute("paths", thePaths);
		}

		return "secure/organization/paths-check-removed";
	}

	/**
	 * Remove paths.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String deletePaths(final HttpServletRequest request, final HttpServletResponse response) {
		String[] paths = request.getParameterValues("elements");

		if(paths != null) {
			Integer[] pathIds = new Integer[paths.length];

			for(int i = 0; i < paths.length; ++i) {
				pathIds[i] = Integer.parseInt(paths[i]);
			}

			knowledgePathDAO.remove(pathIds);
		}

		return "secure/organization/paths-removed";
	}
}
